import { FC, ReactElement, useEffect, useState } from "react";
import styled, { css, CSSObject } from "styled-components";
import { flexCenter } from "../components/BUI/styled";
import { ThemePrimaryBgc } from "../components/BUI/View/ThemeView";

interface IProps {
  cardStyle?: CSSObject;
}

interface IData {
  title: string;
  article: string;
  component?: ReactElement;
}

const data: IData[] = [
  {
    title: "HTML",
    article: "超文本标记语言",
  },
  {
    title: "CSS",
    article: "层叠样式表",
  },
  {
    title: "REACT",
    article: "用于构建用户界面的 JavaScript 库",
  },
  {
    title: "JAVASCRIPT",
    article: "解释型或即时编译型的编程语",
  },
  {
    title: "TYPESCRIPT",
    article: "TypeScript是js的超集",
    component: (
      <>
        <h2>TypeScript</h2>
        <h1>TypeScript是js的超集</h1>
      </>
    ),
  },
];

const sm = 1; //小图
const smOpacity = 0.6;
const smLateX = 16;
const ms = 2; //中图
const msOpacity = 0.8; //中图
const msLateX = 8;
const lg = 3; //大图
const lgOpacity = 1;

type Obj<T> = { [key: string]: T };

const IndexObj: Obj<number> = { sm, ms, lg };

const Swipe: FC<IProps> = ({ cardStyle = {} }): ReactElement => {
  const [index, setIndex] = useState(0);
  const [direction, setDirection] = useState(0); //左 -1 右 1
  const [list, setList] = useState(data);

  const { length } = list;

  const getDate = (index: number): IData =>
    list[index >= length ? index - length : index];

  const handleChange = (num: 1 | -1) => () => {
    setIndex(index => {
      const next = index + num * -1;
      return next >= length ? 0 : next < 0 ? length - 1 : next;
    });
    setDirection(num * -1);
  };

  return (
    <Container cardStyle={cardStyle}>
      <aside>
        <header />
        <Main>
          <ArrowIcon onClick={handleChange(-1)} />
          <Card direction={direction} data={getDate(index)} zIndex={sm} />
          <Card direction={direction} data={getDate(index + 1)} zIndex={ms} />
          <Card direction={direction} data={getDate(index + 2)} zIndex={lg} />
          <Card
            direction={direction}
            data={getDate(index + 3)}
            zIndex={ms}
            right={true}
          />
          <Card
            direction={direction}
            data={getDate(index + 4)}
            zIndex={sm}
            right={true}
          />
          <ArrowIcon onClick={handleChange(1)} right />
        </Main>
      </aside>
      <aside />
    </Container>
  );
};

export default Swipe;

interface ICard {
  zIndex: number;
  right?: boolean;
  data: IData;
  direction: number;
}

const Card: FC<ICard> = ({ zIndex, right, data, direction }) => {
  const [prev, setPrev] = useState(data);
  const [move, setMove] = useState(false);

  useEffect(() => {
    if (prev.title !== data.title) {
      setMove(true);
      setTimeout(() => {
        setPrev(data);
        setMove(false);
      }, 300);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [data]);

  return (
    <CardStyled zIndex={zIndex} right={right} move={move} direction={direction}>
      {prev.component ? (
        prev.component
      ) : (
        <>
          <h1>{prev.title}</h1>
          <article>{prev.article}</article>
        </>
      )}
    </CardStyled>
  );
};

interface ICardStyled extends Omit<ICard, "data"> {
  move: boolean;
}

const CardStyled = styled.div<ICardStyled>`
  position: absolute;
  z-index: ${({ zIndex }) => zIndex};
  width: 22rem;
  height: 16rem;
  ${({ zIndex, right }) =>
    zIndex !== lg &&
    css`
      transform: ${() =>
        `translateX(${
          (zIndex === sm ? smLateX : msLateX) * (right ? 1 : -1)
        }rem) scale(${zIndex === ms ? msOpacity : smOpacity})`};
      opacity: ${zIndex === sm ? smOpacity : msOpacity};
      /* filter: brightness(0.5) */
    `};
  ${ThemePrimaryBgc};
  color: #fff;
  ${flexCenter};
  flex-direction: column;
  border-radius: 0.5rem;

  article {
    width: 90%;
    margin: 0 auto;
    text-align: center;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
  /* font-size: 1.5rem; */

  ${({ move, zIndex, right, direction }) => {
    if (move) {
      if (zIndex === lg) {
        return css`
          transition: all 0.3s linear;
          /* transition-property: opacity, transform; */
          transform: ${`translateX(${msLateX * direction * -1}rem) scale(0.8)`};
          opacity: ${msOpacity};
          z-index: ${IndexObj.ms};
        `;
      } else {
        const toMain =
          (right && direction === 1) || (!right && direction === -1);
        if (zIndex === ms) {
          const next = smLateX * (right ? 1 : -1) * direction;
          return css`
            transition: all 0.3s linear;
            transition-property: opacity, transform;
            opacity: ${toMain ? lgOpacity : smOpacity};
            transform: ${() =>
              `translateX(${toMain ? 0 : next * (right ? -1 : 1)}rem) scale(${
                toMain ? 1 : 0.6
              })`};
            ${`z-index:${IndexObj[toMain ? "lg" : "sm"]};`};
          `;
        } else {
          return css`
            transition: all 0.3s linear;
            ${toMain
              ? `transform: translate(${
                  msLateX * direction
                }rem) scale(0.8);opacity:${msOpacity}`
              : `transform: translate(${
                  msLateX * direction * 2
                }rem) scale(0.6);`};
          `;
        }
      }
    }
    return "";
  }}
`;

const d = (
  <svg
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="2415"
    width="32"
    height="32"
  >
    <path
      d="M378.24 512l418.88 418.88L704 1024 192 512l512-512 93.12 93.12z"
      fill="#ffffff"
      p-id="2416"
    ></path>
  </svg>
);

const ArrowIcon = styled.div.attrs({
  children: d,
})<{ right?: boolean }>`
  padding: 3px 5px;
  background-color: #0000007d;
  position: absolute;
  ${({ right }) => (right ? "right:0;transform:rotate(-180deg)" : "left:0")};
  width: 2rem;
  height: 3rem;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  transition: background-color 0.3s linear;
  :hover {
    background-color: #000000c8;
  }
`;

const Main = styled.div`
  height: 22rem;
  width: 100%;
  position: relative;
  background-color: #ccc;
  display: flex;
  justify-content: center;
  align-items: center;
`;

const Container = styled.div<{ cardStyle: CSSObject }>`
  height: 100vh;
  width: 100vw;
  background-color: #fffae5;
  display: flex;
  aside:first-child {
    flex: 2;
    & > header {
      height: 4rem;
      width: 100%;
      background: #faa;
    }
  }
  aside:last-child {
    flex: 1;
    background: #eee;
  }
  ${CardStyled} {
    ${({ cardStyle }) => ({ ...cardStyle })};
  }
`;
